package com.netty.tcp;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
public class MessageDecoder2 extends LengthFieldBasedFrameDecoder {

    public MessageDecoder2(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength) {
        super(maxFrameLength, lengthFieldOffset, lengthFieldLength);
    }
    //需要确认是否线程安全
    /**是否在读取头部*/
    private volatile AtomicBoolean readComplete = new AtomicBoolean(true);
    /**报文的长度*/
    private volatile AtomicInteger msglen = new AtomicInteger(0);
    /**报文本身*/
    private MsgObj obj = null;
    private int offset = 8;

    @Override
    protected MsgObj decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
        //此段代码需求确认是否现场安全

        if (readComplete.get()){
            byte[] headbuff = new byte[offset];
            in.readBytes(headbuff);
            String header = new String(headbuff);
            msglen = new AtomicInteger(Integer.valueOf(header));
            if (obj == null){
                obj = new MsgObj();
                obj.setHeader(msglen.get());
                obj.setBody("");
            }
        }
        int bd = in.readableBytes() ;
        //考虑拆包
        if (bd < msglen.get() ){
            readComplete.set(false);
            log.info("发生拆包。需要循环读取剩下的报文");
            msglen.set(msglen.get() - bd);
            byte[] tmpbody = new byte[bd];
            in.readBytes(tmpbody);
            String body = obj.getBody();
            body = body + new String(tmpbody);
            obj.setBody(body);
            //读取剩下的报文
            //ctx.read()
        }else {
            // 重置状态
            readComplete.set(true);
            msglen.set(0);
            byte[] tmpbody = new byte[bd];
            in.readBytes(tmpbody);
            String body = obj.getBody();
            body = body + new String(tmpbody);
            obj.setBody(body);
        }
        return obj;
    }
}
